package org.dromara.authcode.controller;

import java.util.List;

import cn.dev33.satoken.annotation.SaIgnore;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.authcode.service.IAuthorizedService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.authcode.domain.vo.DeviceAuthVo;
import org.dromara.authcode.domain.bo.DeviceAuthBo;
import org.dromara.authcode.service.IDeviceAuthService;
import org.dromara.common.mybatis.core.page.TableDataInfo;

/**
 * 设备授权记录
 *
 * @author Miles Meng
 * @date 2025-08-08
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/authcode/auth")
public class DeviceAuthController extends BaseController {

    private final IDeviceAuthService deviceAuthService;
    private final IAuthorizedService authorizedService;

    /**
     * 查询设备授权记录列表
     */
    @SaCheckPermission("authcode:auth:list")
    @GetMapping("/list")
    public TableDataInfo<DeviceAuthVo> list(DeviceAuthBo bo, PageQuery pageQuery) {
        return deviceAuthService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出设备授权记录列表
     */
    @SaCheckPermission("authcode:auth:export")
    @Log(title = "设备授权记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(DeviceAuthBo bo, HttpServletResponse response) {
        List<DeviceAuthVo> list = deviceAuthService.queryList(bo);
        ExcelUtil.exportExcel(list, "设备授权记录", DeviceAuthVo.class, response);
    }

    /**
     * 获取设备授权记录详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("authcode:auth:query")
    @GetMapping("/{id}")
    public R<DeviceAuthVo> getInfo(@NotNull(message = "主键不能为空")
                                   @PathVariable Long id) {
        return R.ok(deviceAuthService.queryById(id));
    }

    /**
     * 新增设备授权记录
     */
    @SaCheckPermission("authcode:auth:add")
    @Log(title = "设备授权记录", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody DeviceAuthBo bo) {
        return toAjax(deviceAuthService.insertByBo(bo));
    }

    /**
     * 修改设备授权记录
     */
    @SaCheckPermission("authcode:auth:edit")
    @Log(title = "设备授权记录", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody DeviceAuthBo bo) {
        return toAjax(deviceAuthService.updateByBo(bo));
    }

    /**
     * 删除设备授权记录
     *
     * @param ids 主键串
     */
    @SaCheckPermission("authcode:auth:remove")
    @Log(title = "设备授权记录", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(deviceAuthService.deleteWithValidByIds(List.of(ids), true));
    }

    /**
     * 设备授权,或者App授权，或者App某项功能授权
     * 扫描二维码参考下面的authByQRCode
     * 集成在这个接口中，方便用户使用
     * bo.authCode的格式：MAC|dateTime|authCode
     * todo: 添加设备授权记录
     * @param bo 授权码信息
     */
    @SaIgnore
    @PostMapping("/authApp")
    public R<Void> authApp(
        @RequestBody DeviceAuthBo bo) {
        // 解密授权码
        String code = authorizedService.decryptAuthorizedCode(bo.getAuthCode());
        if (authorizedService.checkDateTime(code)) {
            return R.fail("授权码请求已过期");
        } else {
            // 转换Mac地址. 赋值给bo
            bo.setMacAddress(authorizedService.getMacAddress(code));
            // 转换授权码. 赋值给bo
            bo.setAuthCode(authorizedService.getAuthCode(code));
        }

        if (!deviceAuthService.activeDevice(bo)) {
            return R.fail("授权失败");
        }

        return R.ok("授权成功");
    }

    /**
     * 授权激活功能（二维码授权）
     * TODO 待完善
     * App扫描二维码后获取授权码authCode，然后拼装Mac地址和时间MAC|dateTime|authCode
     * 本功能和authApp功能一样，只是在没有录入mac地址到系统的情况，自动生成设备表数据
     * 没有合并的原因是，二维码是可信可控的，界面输入授权码是不可控的？？？
     * @param bo 授权码信息，mac地址，授权码
     * bo.authCode的格式：MAC|dateTime|authCode
     * bo.authCode: 授权码
     * bo.macAddress: mac地址
     * @return 是否授权成功
     */
    @SaIgnore
    @PostMapping("/authByQRCode")
    public R<Boolean> authByQRCode(
        @RequestBody DeviceAuthBo bo) {
        // 解密授权码
        String code = authorizedService.decryptAuthorizedCode(bo.getAuthCode());
        if (authorizedService.checkDateTime(code)) {
            return R.fail("授权码请求已过期");
        } else {
            // 转换Mac地址. 赋值给bo
            bo.setMacAddress(authorizedService.getMacAddress(code));
            // 转换授权码. 赋值给bo
            bo.setAuthCode(authorizedService.getAuthCode(code));
        }

        if (!deviceAuthService.activeDeviceByQrCode(bo)) {
            return R.fail("授权失败");
        }

        return R.ok("授权成功");
    }

    /**
     * 检查授权状态
     * bo.authCode的格式：MAC|dateTime 没有授权码的情况：直接检查后台授权码情况
     * bo.goodsId: 商品ID，后续考虑App界面商品和功能对应，现在固定传1
     * @param bo 授权码信息
     *
     * @return 是否授权
     */
    @SaIgnore
    @PostMapping("/checkAuth")
    public R<Boolean> checkAuth(
        @RequestBody DeviceAuthBo bo) {
        // 解密授权码
        String code = authorizedService.decryptAuthorizedCode(bo.getAuthCode());

        if (authorizedService.checkDateTime(code)) {
            return R.fail("授权码请求已过期");
        } else {
            // 转换Mac地址. 赋值给bo
            bo.setMacAddress(authorizedService.getMacAddress(code));
        }

        if (!deviceAuthService.checkFunction(bo)) {
            return R.fail("授权失败");
        }

        return R.ok("已授权");
    }

}
